<template>
  <el-card ref="card">
    <template #header>
      <el-row class="mapView">
        <el-col :span="8">
          <el-input
            v-model="mapName"
            style="width: 250px"
            addon-before="地图名"
          />
          <el-button type="primary" @click="openMap"> 打开 </el-button>
        </el-col>
        <el-col :span="5">
          <el-button-group class="ml-4">
            <el-button
              type="primary"
              :icon="useRenderIcon(Curve)"
              @click="draw_line"
            />
            <el-button
              type="primary"
              :icon="useRenderIcon(Eraser)"
              @click="eraser"
            />
            <el-button
              type="primary"
              :icon="useRenderIcon(Undo)"
              @click="undo"
            />
          </el-button-group>
        </el-col>
        <span v-if="drawLine || drawEraser" class="slider-demo-block"
          >粗细
        </span>
        <el-col :span="5">
          <el-slider
            v-if="drawLine"
            v-model="line_width"
            show-input
            :min="0.1"
            :max="10"
            :step="0.1"
            @input="handleLineChange"
          />
          <el-slider
            v-else-if="drawEraser"
            v-model="eraser_width"
            show-input
            :min="0.1"
            :max="10"
            :step="0.1"
            @input="handleEraserChange"
          />
        </el-col>
        <el-col :span="2" :offset="1">
          <el-button
            type="warning"
            :icon="Upload"
            @click="dialogVisible = true"
          >
            保存
          </el-button>
        </el-col>
        <el-dialog
          v-model="dialogVisible"
          title="请输入保存的名称"
          :width="300"
        >
          <el-input
            v-model="map_Name"
            placeholder="请输入名称"
            style="margin-bottom: 20px"
          />
          <template v-slot:footer>
            <div class="dialog-footer" style="text-align: right">
              <el-button size="small" @click="dialogVisible = false"
                >取 消</el-button
              >
              <el-button type="danger" size="small" @click="save_map"
                >确 定</el-button
              >
            </div>
          </template>
        </el-dialog>
      </el-row>
    </template>

    <div class="canvas-container">
      <canvas ref="canvas" class="centered-canvas" />
    </div>
  </el-card>
</template>

<script setup lang="ts">
import { ref, reactive } from "vue";
import axios from "axios";
import MapEditor from "@/api/mapEditor";
import { ElMessage } from "element-plus";
import { ip } from "@/api/utils";
import { Upload } from "@element-plus/icons-vue";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Curve from "@iconify-icons/fad/softclipcurve";
import Eraser from "@iconify-icons/fad/eraser";
import Undo from "@iconify-icons/fad/undo";

const mapName = ref("map");
const card = ref(null);
const dialogVisible = ref(false);
const drawLine = ref(false);
const drawEraser = ref(false);
const line_width = ref(2);
const eraser_width = ref(4);

const globalState = reactive({
  flag: "",
  color: "#000000",
  lineWidth: 5,
  eraserWidth: 5
});

const handleLineChange = value => {
  globalState.lineWidth = value;
};

const handleEraserChange = value => {
  globalState.eraserWidth = value;
};

const canvas = ref<HTMLCanvasElement | null>(null);
let stage;
let shape;
const shapesArray = [];
const openMap = () => {
  stage = new createjs.Stage(canvas.value);
  stage.enableDOMEvents(true);
  createjs.Ticker.timingMode = createjs.Ticker.RAF;
  createjs.Ticker.on("tick", stage);
  createjs.Touch.enable(stage);
  const mapEditor = new MapEditor(mapName.value, stage);
  mapEditor.openMap();

  let oldX, oldY;
  let isDrawing = false;
  shape = new createjs.Shape();
  stage.on("stagemousedown", function (event) {
    if (globalState.flag !== "line" && globalState.flag !== "eraser") return;
    isDrawing = true;
    oldX = event.stageX;
    oldY = event.stageY;
    shape = new createjs.Shape();
  });
  stage.on("stagemouseup", function () {
    if (globalState.flag !== "line" && globalState.flag !== "eraser") return;
    isDrawing = false;
    if (shape) {
      shapesArray.push(shape);
      stage.addChild(shape);
      stage.update();
      shape = null;
    }
  });
  stage.on("stagemousemove", function (evt) {
    if (
      (globalState.flag !== "line" && globalState.flag !== "eraser") ||
      !isDrawing
    )
      return;
    if (globalState.flag === "eraser") {
      globalState.color = "#ffffff";
      globalState.lineWidth = globalState.eraserWidth;
    } else {
      globalState.color = "#000000";
    }
    shape.graphics
      .beginStroke(globalState.color)
      .setStrokeStyle(globalState.lineWidth, "round")
      .moveTo(oldX, oldY)
      .lineTo(evt.stageX, evt.stageY);
    stage.addChild(shape);
    stage.update();
    oldX = evt.stageX;
    oldY = evt.stageY;
  });
};

const draw_line = () => {
  drawLine.value = true;
  drawEraser.value = false;
  globalState.flag = "line";
};

const eraser = () => {
  drawEraser.value = true;
  drawLine.value = false;
  globalState.flag = "eraser";
};

const undo = () => {
  if (shapesArray.length === 0) return;
  const lastShape = shapesArray.pop();
  stage.removeChild(lastShape);
  stage.update();
  // shape = new createjs.Shape();
};

const getblob = (canvasRef: HTMLCanvasElement | null) => {
  if (!canvasRef) return;
  const canvas = canvasRef;
  const ctx = canvas.getContext("2d");
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const pgmData = new Uint8Array(canvas.width * canvas.height);
  for (let i = 0; i < imageData.data.length; i += 4) {
    const r = imageData.data[i];
    const g = imageData.data[i + 1];
    const b = imageData.data[i + 2];
    const gray = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
    pgmData[i / 4] = gray;
  }
  const header = "P5\n" + canvas.width + " " + canvas.height + "\n" + "255\n";
  const data = new Uint8Array(header.length + pgmData.length);
  for (let i = 0; i < header.length; i++) {
    data[i] = header.charCodeAt(i);
  }
  data.set(pgmData, header.length);
  const blob = new Blob([data.buffer], { type: "image/x-portable-graymap" });
  return blob;
};

const percentage = ref(0);
const uploadAs = (blob, filename) => {
  console.log("Original filename:", filename);
  const file = new File([blob], filename, {
    type: "image/pgm",
    lastModified: Date.now()
  });
  const formData = new FormData();
  formData.append("file", file);

  axios({
    method: "post",
    url: "http://" + ip("5000/upload"),
    data: formData,
    onUploadProgress: e => {
      percentage.value = Math.round((e.loaded * 100) / e.total);
      console.log("Percentage:", percentage.value);
    }
  })
    .then(function () {
      ElMessage({
        message: "上传地图成功!",
        type: "success"
      });
      // console.log("responseText: ", response.data);
    })
    .catch(function (error) {
      if (error.response) {
        ElMessage.error("上传地图失败!");
        // 请求已发出，但服务器响应的状态码不在 2xx 范围内
        // console.log("上传地图失败!");
      } else {
        ElMessage.error("上传地图请求错误!");
        // 发送请求时出了问题，或者处理请求时出了问题
        // console.log('上传地图请求错误！');
      }
    });
};

const map_Name = ref("");
const save_map = () => {
  const blob = getblob(canvas.value);
  uploadAs(blob, `${map_Name.value}.pgm`);
  dialogVisible.value = false;
};
</script>

<style lang="scss" scoped>
.flex_r_b {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.mx-1 {
  position: absolute;
  right: 0;
  top: 0;
  width: auto;
  height: auto;
  border: 3px solid var(--el-border-color);
}

.map-container {
  width: 70vw;
  height: 75vh;
  position: relative;
}

.el-dialog__wrapper[fullscreen="true"] .el-dialog {
  width: 100% !important;
  height: 100% !important;
  max-height: none !important;
  margin: 0 !important;
}

.dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.dialog-fullscreen-button {
  color: #606266;
}

.canvas-container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
}

.centered-canvas {
  border: 1px solid black;
  height: 80vmin;
}

.slider-demo-block {
  max-width: 600px;
  display: flex;
  align-items: center;
  flex: 0.1;
}
</style>
